package com.github.rnewson.couchdb.lucene;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.log4j.Logger;
import org.apache.lucene.store.FSDirectory;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.javascript.ClassShutter;
import org.mozilla.javascript.Context;

import com.github.rnewson.couchdb.lucene.couchdb.Database;
import com.github.rnewson.couchdb.lucene.index.CouchIndex;

public final class GenerateWebs implements Runnable, ResponseHandler<Void> {

	private final class RestrictiveClassShutter implements ClassShutter {

		public boolean visibleToScripts(final String fullClassName) {
			return false;
		}
	}

	private final HttpClient client;

	private boolean closed;

	private Context context;

	private final Database database;

	// private long ddoc_seq;
	//
	// private long lastCommit;

	private final CountDownLatch latch = new CountDownLatch(1);

	public void intii() {
		Thread no = new Thread();
		no.setPriority(0);

	}

	private final Logger logger;

	// private final Map<String, View> paths = new HashMap<String, View>();

	private HttpUriRequest req;

	private final File root;

	private long since;

	// private final Map<View, IndexState> states = Collections
	// .synchronizedMap(new HashMap<View, IndexState>());

	private UUID uuid;

	private final HierarchicalINIConfiguration ini;

	public GenerateWebs(final HttpClient client, final File root,
			final Database database, final HierarchicalINIConfiguration ini)
			throws IOException, JSONException {
		this.client = client;
		this.root = root;
		this.database = database;
		this.ini = ini;
		this.logger = Logger.getLogger(DatabaseIndexer.class.getName() + "."
				+ database.getInfo().getName());
	}
static int count=0;
	public Void handleResponse(final HttpResponse response)
			throws ClientProtocolException, IOException {
		final HttpEntity entity = response.getEntity();
		final BufferedReader reader = new BufferedReader(new InputStreamReader(
				entity.getContent(), "UTF-8"));
		String line;

		String databasename = this.database.getURL();

		AbstractGenerationPoll generationPoll = new GenePollUseThreadPoll(10);// 获得一个生存对象池
		generationPoll = generationPoll.getGenerationPoll();// singleton

		// AbstractGenerationPoll generationPoll = new GenerationPoll(10);
		loop: while ((line = reader.readLine()) != null) {
			// maybeCommit();
			System.out.println(count++);
			// Heartbeat.
			if (line.length() == 0) {
				logger.trace("heartbeat");
				continue loop;
			}

			try {
				final JSONObject json = new JSONObject(line);

				if (json.has("error")) {
					logger.warn("Indexing stopping due to error: " + json);
					break loop;
				}

				if (json.has("last_seq")) {
					logger.warn("End of changes detected.");
					break loop;
				}

				final long seq = json.getLong("seq");
				final String id = json.getString("id");

				int len = this.database.getURL().length() - 1;
				String fileName = this.database.getURL().substring(0, len);
				fileName = fileName.replace('/', '_');
				fileName = fileName.replace(':', '_');
				File f = new File("F:\\couchdb\\" + fileName);
				FileWriter fw;
				try {
					fw = new FileWriter(f);
					BufferedWriter output = new BufferedWriter(fw);
					String n = String.valueOf(seq);
					output.write(n);
					output.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String baseDir = "F:/index";
				File file = new File(baseDir);
//				if (!file.exists())
//					file.mkdirs();
				
				String indexPath = baseDir + File.separator + id;
				CouchIndex ci = new CouchIndex(indexPath);
				ci.addNewDoc(ci.getDocmentFromJson(json));
				ci.closeIndex();
				//ci=null;
				// 我的写序号
				// FileOutputStream out = new FileOutputStream("/home/zzhj/a");
				// PrintStream p = new PrintStream(out);
				// String record = Long.toString(seq);
				// p.println(record);
				// out.close();

				AbstractGeneration generation = generationPoll
						.getGeneration(databasename);
				generation.generateWeb(line);
				// System.out.println(line);

				// CouchDocument doc;
				// if (!json.isNull("doc")) {
				// doc = new CouchDocument(json.getJSONObject("doc"));
				// } else {
				// // include_docs=true doesn't work prior to 0.11.
				// try {
				// doc = database.getDocument(id);
				// } catch (final HttpResponseException e) {
				// switch (e.getStatusCode()) {
				// case HttpStatus.SC_NOT_FOUND:
				// doc = CouchDocument.deletedDocument(id);
				// break;
				// default:
				// logger.warn("Failed to fetch " + id);
				// break loop;
				// }
				// }
				// }
				//
				// if (id.startsWith("_design")) {
				// if (seq > ddoc_seq) {
				// logger.info("Exiting due to design document change.");
				// break loop;
				// }
				// for (final IndexState state : states.values()) {
				// state.setPendingSequence(seq);
				// }
				// continue loop;
				// }
				//
				// if (doc.isDeleted()) {
				// for (final IndexState state : states.values()) {
				// state.writer.deleteDocuments(new Term("_id", id));
				// state.setPendingSequence(seq);
				// state.readerDirty = true;
				// }
				// } else {
				// for (final Entry<View, IndexState> entry : states.entrySet())
				// {
				// final View view = entry.getKey();
				// final IndexState state = entry.getValue();
				//
				// if (seq > state.pending_seq) {
				// final Document[] docs;
				// try {
				// docs = state.converter.convert(doc, view
				// .getDefaultSettings(), database);
				// } catch (final Exception e) {
				// logger.warn(id + " caused " + e.getMessage());
				// continue loop;
				// }
				//
				// state.writer.deleteDocuments(new Term("_id", id));
				// for (final Document d : docs) {
				// state.writer.addDocument(d, view.getAnalyzer());
				// state.writerDirty = true;
				// }
				// state.setPendingSequence(seq);
				// state.readerDirty = true;
				// }
				// }
				// }
			} catch (final JSONException e) {
				logger.error("JSON exception in changes loop", e);
				break loop;
			}
		}

		generationPoll.closeThread();
		req.abort();
		return null;
	}

	public void run() {
		if (closed) {
			throw new IllegalStateException("closed!");
		}

		try {
			try {

				// int s2;
				// try {
				int len = this.database.getURL().length() - 1;
				String fileName = this.database.getURL().substring(0, len);
				fileName = fileName.replace('/', '_');
				fileName = fileName.replace(':', '_');
				File f = new File("F:\\couchdb\\" + fileName);
				if (f.exists()) {
					BufferedReader input = new BufferedReader(new FileReader(f));
					// int s2 = Integer.parseInt(input.readLine());
					String s1 = input.readLine();
					// System.out.println(s1);
					since = Integer.parseInt(s1);
					input.close();
				} else {
					since = 1;
				}
//

				// req = database.getChangesRequest(s2);
				// logger.info("Indexing from update_seq " + s2);
				// client.execute(req, this);
				// } finally {
				// close();
				// }

				// 我的读序号
				// File file = new File("/home/zzhj/a");
				// BufferedReader br = new BufferedReader(new FileReader(file));
				// String temp = null;
				// temp = br.readLine();
				// long since = Long.valueOf(temp);
				// br.close();

				req = database.getChangesRequest(since);
				logger.info("Indexing from update_seq " + since);
				client.execute(req, this);
			} finally {
				close();
			}
		} catch (final SocketException e) {
			// Ignored because req.abort() does this.
		} catch (final Exception e) {
			logger.warn("Exiting due to exception.", e);
			close();
		}
	}

	// private String[] getQueryStrings(final HttpServletRequest req) {
	// return Utils.splitOnCommas(req.getParameter("q"));
	// }

	private void close() {
		this.closed = true;

		if (context != null) {
			Context.exit();
			context = null;
		}
		latch.countDown();
	}

	public boolean isClosed() {
		return closed;
	}

	private String toPath(final String ddoc, final String view) {
		return ddoc + "/" + view;
	}

}
